package de.muehle;

import java.util.Vector;

import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.image.TextureLoader;

import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector3d;

public class MuehleModelle extends BranchGroup {

	public MuehleModelle() {
		float hausheight = 9;
		float hausWidth1 = 12f;
		float hausWidth2 = 7f;
		float domeHeight = hausheight / 2;
		float domeWidth1 = hausWidth2 + 1;
		float domeWidth2 = hausWidth2 - hausWidth2 / 2;

		VentilShape ventilShape = new VentilShape(2.3f * domeHeight, 1.5f, 0.2f);
		BoxHaus boxHaus = new BoxHaus(hausWidth1, hausWidth2, hausheight);
		BoundingSphere boundingSphere = new BoundingSphere(new Point3d(0.0, hausheight + 3 * domeHeight / 4, 5 * domeWidth2 / 4), 1.0);
		Transform3D translate = new Transform3D();
		Transform3D animTrans = new Transform3D();
		Transform3D rotVentil = new Transform3D();
		rotVentil.rotX(Math.PI / 2);
		translate.set(new Vector3d(0, hausheight + 1 * domeHeight / 2,5 * domeWidth2 / 4));
		animTrans.set(new Vector3d(0, hausheight + 1 * domeHeight / 2,5 * domeWidth2 / 4));
		translate.mul(rotVentil);
		TransformGroup ventilTrans = new TransformGroup(translate);
		ventilTrans.addChild(ventilShape);

		TransformGroup domeTrans = addDomeShape(hausheight, domeHeight,	domeWidth1, domeWidth2);
		Cylinder connectionVentil = new Cylinder(1f, 3f);
		Transform3D posCylinder = new Transform3D();
		Transform3D rotCylinder = new Transform3D();
		posCylinder.set(new Vector3d(0, hausheight + 1 * domeHeight / 2,5 * domeWidth2 / 4 - 1));
		rotCylinder.rotX(Math.PI / 2);
		posCylinder.mul(rotCylinder);

		TransformGroup transCylinder = new TransformGroup(posCylinder);
		transCylinder.addChild(connectionVentil);
		Transform3D spinT3D = new Transform3D();
		spinT3D.rotX(Math.toRadians(90));
		animTrans.mul(spinT3D);
		TransformGroup rotationXform = new TransformGroup();
		rotationXform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		Alpha rotationAlpha = new Alpha(-1, 20000);
		RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, rotationXform);
		rotator.setTransformAxis(animTrans);
		rotator.setSchedulingBounds(boundingSphere);
		rotationXform.addChild(rotator);
		rotationXform.addChild(ventilTrans);

		addChild(domeTrans);
		addChild(boxHaus);
		addChild(transCylinder);
		addChild(rotationXform);

		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0);
		Color3f light1Color = new Color3f(.7f, .7f, .7f);
		Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
		DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction);
		light1.setInfluencingBounds(bounds);
		addChild(light1);
		Color3f ambientColor = new Color3f(.4f, .4f, .4f);
		AmbientLight ambientLightNode = new AmbientLight(ambientColor);
		ambientLightNode.setInfluencingBounds(bounds);
		addChild(ambientLightNode);

		compile();
	}

	private TransformGroup addDomeShape(float hausheight, float domeHeight,	float domeWidth1, float domeWidth2) {
		int precisionCurve = 4;
		float k = 60;
		float baseHeight = 1;
		float R = domeWidth1;
		Transform3D translateDome = new Transform3D();
		translateDome.set(new Vector3d(0, hausheight, 0));
		TransformGroup domeTrans = new TransformGroup(translateDome);

		float deltaHeight = domeHeight / precisionCurve;
		float baseWidth = domeWidth1;
		float heightWidth = domeWidth2;
		for (int i = 0; i < precisionCurve; i++) {
			heightWidth = R	+ (float) Math.sqrt(baseHeight + k * hausheight) - (float) Math.sqrt(baseHeight + k	* (hausheight + (i + 1) * deltaHeight));
			DomeShape domeShape = new DomeShape(baseWidth, heightWidth,	deltaHeight);
			Transform3D translateTemp = new Transform3D();
			translateTemp.set(new Vector3d(0, i * deltaHeight, 0));
			TransformGroup transTemp = new TransformGroup(translateTemp);
			transTemp.addChild(domeShape);
			baseWidth = heightWidth;

			domeTrans.addChild(transTemp);
		}
		Shape3D dach = createDach(heightWidth);
		Transform3D translateDach = new Transform3D();
		translateDach.set(new Vector3d(0, domeHeight, 0));
		TransformGroup transDach = new TransformGroup(translateDach);
		transDach.addChild(dach);
		domeTrans.addChild(transDach);
		return domeTrans;
	}

	private Shape3D createDach(float width) {
		IndexedQuadArray pyramidGeometry = new IndexedQuadArray(8, IndexedQuadArray.COORDINATES	| IndexedQuadArray.TEXTURE_COORDINATE_2, 4 * 4);
		Vector<Point3f> vectorPoints = BoxHaus.getVectorPoly(width, 0);
		Point3f[] array = new Point3f[8];
		vectorPoints.toArray(array);
		int[] indices = new int[4 * 4];
		for (int i = 0; i < 4; i++) {
			// Polygone de base
			indices[4 * i] = i;
			indices[4 * i + 1] = (i + 1) % 8;
			indices[4 * i + 2] = (i + 4) % 8;
			indices[4 * i + 3] = (i + 5) % 8;
		}
		pyramidGeometry.setCoordinates(0, array);
		pyramidGeometry.setCoordinateIndices(0, indices);
		TextureLoader loader = new TextureLoader("textures/Holz_Streifen.jpg",	null);
		Texture2D tex = (Texture2D) loader.getTexture();

		Appearance app = new Appearance();
		app.setTexture(tex);
		app.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE, 0f));
		return new Shape3D(pyramidGeometry, app);
	}
}